package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.ArticleVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author jack
 * @data 2023 14:41
 */
@Service
public class HotArticleServiceImpl implements HotArticleService {
    @Autowired
    private ApArticleMapper apArticleMapper;
    @Autowired
    private CacheService cacheService;

    /**
     * 计算热点文章
     */
    @Override
    public void computeHotArticle() {
        //1. 查询数据库表：ap_article，得到近5天的文章信息
        //1.1 计算得到一个5天前的时间
        long timeOfFiveDaysAgo = System.currentTimeMillis() - (1000L * 60 * 60 * 24 * 5);
        List<ApArticle> apArticleList = apArticleMapper.selectList(Wrappers.<ApArticle>lambdaQuery().ge(ApArticle::getPublishTime, new Date(timeOfFiveDaysAgo)));

        //2. 给文章进行算分
        List<ArticleVo> articleVos = computeScore(apArticleList);

        //3. 将分值排名前30的文章作为热点文章存入redis
        //3.1 先排出各个频道里的30篇热门文章
        //a. 拿到所有频道
        List<Integer> channelIds = apArticleList.stream().map(ApArticle::getChannelId).distinct().collect(Collectors.toList());
        //b. 遍历各个频道
        for (Integer channelId : channelIds) {
            //对该频道内的文章进行分数排名
            List<ArticleVo> voList = articleVos.stream().filter(articleVo -> articleVo.getChannelId().equals(channelId)).collect(Collectors.toList());
            sortAndSetCache(channelId+"", voList);
        }

        //3.2 再排出"推荐"频道里的30篇热门文章
        sortAndSetCache("__all__",articleVos);
    }

    //对文章进行分数排序并存入redis缓存
    private void sortAndSetCache(String channelId, List<ArticleVo> voList) {
        //按分数降序
        Collections.sort(voList, new Comparator<ArticleVo>() {
            @Override
            public int compare(ArticleVo o1, ArticleVo o2) {
                return o2.getScore() - o1.getScore();
            }
        });
        //截取出集合中前30篇进行热点文章的缓存
        if (voList.size() > 30){
            voList = voList.stream().limit(30).collect(Collectors.toList());
        }
        cacheService.set(ArticleConstants.HOT_ARTICLE+ channelId, JSON.toJSONString(voList));
    }

    /*
        给文章算分:
            a. 一个阅读数据 + 1分
            b. 一个点赞数据 + 3分
            c. 一个评论数据 + 5分
            d. 一个收藏数据 + 8分
     */
    private List<ArticleVo> computeScore(List<ApArticle> apArticleList) {
        if (apArticleList != null && apArticleList.size() > 0) {
            List<ArticleVo> articleVos = apArticleList.stream().map(apArticle -> {
                int score = 0;
                //阅读
                if (apArticle.getViews() != null) {
                    score += apArticle.getViews();
                }
                //点赞
                if (apArticle.getLikes() != null) {
                    score += (apArticle.getLikes() * 3);
                }
                //评论
                if (apArticle.getComment() != null) {
                    score += (apArticle.getComment() * 5);
                }
                //收藏
                if (apArticle.getCollection() != null) {
                    score += (apArticle.getCollection() * 8);
                }
                ArticleVo articleVo = new ArticleVo();
                BeanUtils.copyProperties(apArticle, articleVo);
                articleVo.setScore(score);
                return articleVo;
            }).collect(Collectors.toList());

            return articleVos;
        } else return null;
    }
}
